package ink.ykb.rpn;

import java.math.BigDecimal;
import java.util.Scanner;
import java.util.regex.Pattern;

/**
 * 计算器入口
 *
 */
public class RpnServer {
  
  private Stack<InputData> inputStack;
  
  public static void main(String[] args) {
    //输入的数据
    Stack<InputData> inputStack = new Stack<>();
    RpnServer server = new RpnServer(inputStack);
    //执行
    server.exec();
  }
  
  public RpnServer(Stack<InputData> inputStack) {
    super();
    this.inputStack = inputStack;
  }



  private void exec() {
    
    String input;
    System.out.println("表达式格式为以下几种：");
    System.out.println("1.基础计算公式：含数字，+，-，*，/，(，)");
    System.out.println("2.开方：sqrt 数字 或  sqrt 基础计算公式");
    System.out.println("3.撤消：undo 取消上一步输入");
    System.out.println("4.清空：clear 清空输入的所有信息");
    System.out.println("5.查看：look 查看输入的所有信息");
    System.out.println("6.退出：exit");
    System.out.println("");
    
    Scanner sc = new Scanner(System.in);
    while (true) {
        System.out.print("请输入表达式：");
        //获取输入
        input = sc.nextLine();
        
        if(input.equals("exit")){
            sc.close();
            break;
        }
        
        //判断输入格式
        InputData inputData = convertInput(input);
        if(inputData == null) {
          System.out.println("输入格式错误");
          continue;
        }
        
        if(inputData.getType() == InputType.COMPUTE) {
          inputStack.push(inputData);
          
          InToPost inToPost = new InToPost(input);
          inToPost.doTrans();
          BigDecimal result = inToPost.gotParse();
          System.out.println("后缀表达式:"+inToPost.getOutput());
          System.out.println("结果："+result);
          
        }else if(inputData.getType() == InputType.SQRT) {
          inputStack.push(inputData);
          
          String d = inputData.getInput().substring("sqrt ".length() - 1).trim();
          
          Double result = null;
          if(Pattern.matches("\\d+", d)) {
            result = Math.sqrt(Double.valueOf(d));
          }else {
            InToPost inToPost = new InToPost(d);
            inToPost.doTrans();
            result = Math.sqrt(Double.valueOf(inToPost.gotParse().toPlainString()));
          }
          
          System.out.println("结果："+result);
          
        }else if(inputData.getType() == InputType.UNDO) {
          inputStack.pop();
        }else if(inputData.getType() == InputType.CLEAR) {
          inputStack = new Stack<>();
        }else if(inputData.getType() == InputType.LOOK) {
          System.out.println("栈信息：(top --> bottom)");
          for (int j = 0; j < inputStack.size(); j++) {
            InputData data = inputStack.peekN(j);
            if (data != null) {
              System.out.println("输入："+data.getInput()+"，类型："+data.getType());
            }
          }
        }
        
        System.out.println();
        
    }
  }
  
  
  
  /**
   * 转换输入
   * @param input
   * @return
   */
  private InputData convertInput(String input) {
    InputData data = null;
    
    //判断输入格式
    if(!Pattern.matches("\\d+", input) && Pattern.matches("(\\d+|\\+|-|\\*|/|\\(|\\))+", input)) {
      data = new InputData(input,InputType.COMPUTE);
    }else if(Pattern.matches("sqrt (\\d+|\\+|-|\\*|/|\\(|\\))+", input)) {
      data = new InputData(input,InputType.SQRT);
    }else if(input.equalsIgnoreCase("undo")) {
      data = new InputData(input,InputType.UNDO);
    }else if(input.equalsIgnoreCase("clear")) {
      data = new InputData(input,InputType.CLEAR);
    }else if(input.equalsIgnoreCase("look")) {
      data = new InputData(input,InputType.LOOK);
    }else {
      return null;
    }
    
    return data;
  }

  class InputData{
    
    private String input; 
    
    private InputType type;

    public String getInput() {
      return input;
    }

    public void setInput(String input) {
      this.input = input;
    }

    public InputType getType() {
      return type;
    }

    public void setType(InputType type) {
      this.type = type;
    }

    public InputData(String input, InputType type) {
      super();
      this.input = input;
      this.type = type;
    }

    public InputData() {
      super();
    }

    @Override
    public String toString() {
      return "InputData [input=" + input + ", type=" + type + "]";
    }
    
    
  }
  
  enum InputType {
    
    COMPUTE("基本计算","0"),
    
    SQRT("开方","1"),
    
    UNDO("撤消","2"),
    
    CLEAR("清空","3"),
    
    LOOK("查看","4");
    
    private String name;
    
    private String value;
    
    private InputType(String name, String value) {
      this.name = name;
      this.value = value;
    }
    
    public String getName() {
      return name;
    }

    public String getValue() {
      return value;
    }
    

  }
  
}
